package com.sunyard.utils.wxv3Util;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.sunyard.constant.ErrMessageConst;
import com.sunyard.exception.IllegalOperationException;
import com.sunyard.utils.manage.EosFileUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.net.util.Base64;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author : ziliang.zhou
 * @version : 1.0
 * @date : 2020-09-12 16:56
 * @description :
 **/
@Slf4j
@Service
public class UploadImage {


    public static String updateImage(String url, File file, String merchantId, String certificateSerialNumber, String rsaPublicKeyFile, String rsaPrivateKey, String hostname, String port, String proxy) throws Exception {

        int statusCode = 0;
        String statusMessage = "";
        Map<String, Object> maptmp = new HashMap<>(3);
        //时间戳
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        //随机数
        String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");
        //文件名
        String filename = file.getName();
        //文件sha256
        String fileSha256 = DigestUtils.sha256Hex(new FileInputStream(file));

        //拼签名串
        StringBuilder sb = new StringBuilder();
        sb.append("POST").append("\n");
        sb.append("/v3/merchant/media/upload").append("\n");
        sb.append(timestamp).append("\n");
        sb.append(nonce_str).append("\n");
        sb.append("{\"filename\":\"").append(filename).append("\",\"sha256\":\"").append(fileSha256).append("\"}").append("\n");
        log.info("签名原串:" + sb.toString());

        //计算签名
        String sign = new String(Base64.encodeBase64(signRSA(sb.toString(), rsaPrivateKey)));
        log.info("签名sign值:" + sign);

        //拼装http头的Authorization内容
        String authorization = "WECHATPAY2-SHA256-RSA2048 mchid=\"" + merchantId + "\",nonce_str=\"" + nonce_str + "\",signature=\"" + sign + "\",timestamp=\"" + timestamp + "\",serial_no=\"" + certificateSerialNumber + "\"";
        log.info("authorization值:" + authorization);

        //接口URL
        boolean b = Boolean.parseBoolean(proxy);
        CloseableHttpClient httpclient = null;
        if (b) {
            log.info("代理地址:{},代理端口：{}", hostname, port);
            HttpHost proxy1 = new HttpHost(hostname, Convert.toInt(port), "http");
            RequestConfig defaultRequestConfig = RequestConfig.custom().setProxy(proxy1).build();
            httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).build();
        } else {
            httpclient = HttpClients.createDefault();
        }
        HttpPost httpPost = new HttpPost(url);

        //设置头部
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-Type", "multipart/form-data");
        httpPost.addHeader("Authorization", authorization);

        //创建MultipartEntityBuilder
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
        //设置boundary
        multipartEntityBuilder.setBoundary("boundary");
        multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));
        //设置meta内容
        multipartEntityBuilder.addTextBody("meta", "{\"filename\":\"" + filename + "\",\"sha256\":\"" + fileSha256 + "\"}", ContentType.APPLICATION_JSON);
        //设置图片内容
        multipartEntityBuilder.addBinaryBody("file", file, ContentType.create("image/jpg"), filename);
        //放入内容
        httpPost.setEntity(multipartEntityBuilder.build());

        //获取返回内容
        CloseableHttpResponse response = httpclient.execute(httpPost);
        statusCode = response.getStatusLine().getStatusCode();
        statusMessage = response.getStatusLine().getReasonPhrase();
        log.info("微信返回状态码:" + statusCode);
        log.info("微信返回信息:" + statusMessage);
        HttpEntity httpEntity = response.getEntity();
        String rescontent = new String(InputStreamTOByte(httpEntity.getContent()));
        JSONObject jsonObject = JSON.parseObject(rescontent);
        log.info("微信上传图片返回内容:" + rescontent);
        //获取返回的http header
        Header headers[] = response.getAllHeaders();
        int i = 0;
        while (i < headers.length) {
            System.out.println(headers[i].getName() + ":  " + headers[i].getValue());
            i++;
        }
        EntityUtils.consume(httpEntity);
        response.close();
        if (200 == response.getStatusLine().getStatusCode()) {
            return jsonObject.getString("media_id");
        } else {
            if (jsonObject != null) {
                throw new IllegalOperationException("微信返回异常:" + jsonObject.get("message"));
            } else {
                throw new IllegalOperationException("微信返回异常:" + rescontent);
            }
        }
    }

    public static byte[] InputStreamTOByte(InputStream in) throws IOException {

        int BUFFER_SIZE = 4096;
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] data = new byte[BUFFER_SIZE];
        int count = -1;

        while ((count = in.read(data, 0, BUFFER_SIZE)) != -1) {
            outStream.write(data, 0, count);
        }

        data = null;
        byte[] outByte = outStream.toByteArray();
        outStream.close();

        return outByte;
    }


    public static byte[] signRSA(String data, String priKey) throws Exception {
        //签名的类型

        Signature sign = Signature.getInstance("SHA256withRSA");

        //读取商户私钥,该方法传入商户私钥证书的内容即可

        byte[] keyBytes = Base64.decodeBase64(priKey);

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        sign.initSign(privateKey);

        sign.update(data.getBytes(StandardCharsets.UTF_8));

        return sign.sign();

    }


    public static boolean verifyRSA(String data, byte[] sign, String pubKey) throws Exception {

        if (data == null || sign == null || pubKey == null) {

            return false;

        }


        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        FileInputStream in = new FileInputStream(pubKey);

        Certificate c = cf.generateCertificate(in);

        in.close();

        PublicKey publicKey = c.getPublicKey();

        Signature signature = Signature.getInstance("SHA256WithRSA");

        signature.initVerify(publicKey);

        signature.update(data.getBytes("UTF-8"));

        return signature.verify(sign);

    }

    public static File downloadFile(String local) {
        try {
            //byte[] bytes = FastdfsUtils.testDownload(local, fastdfsConfigLocal);
            //byte[] bytes = FileUtil.readBytes(local);
            byte[] bytes = EosFileUtils.downloadFileByte(local);
            File file = null;
            if (bytes != null) {
                String fileName = local.substring(local.lastIndexOf("/") + 1);
                String filepath = "src/main/resources/" + fileName;
                file = new File(filepath);
                if (file.exists()) {
                    file.delete();
                }
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(bytes, 0, bytes.length);
                fos.flush();
                fos.close();
            }
            return file;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void deleteFile(String fileName) {
        String filepath = "src/main/resources/" + fileName;
        File file = new File(filepath);
        if (file.exists()) {
            file.delete();
        }
    }

    public static void main(String[] args) throws Exception {
        /*File file=new File("C:\\Users\\ziliang.zhou\\Pictures\\Camera Roll\\1.jpg");
        String result = UploadImage.updateImage("https://api.mch.weixin.qq.com/v3/merchant/media/upload",file,"1423599102","23ABB448A8F3830B8D3D48187A6821D8AF7E6552",null,"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDGpcdU12Sco6EGaEDXKqm9RlteM8xy5QHheVAOArtsfetMcfjEqGMfGvehsIS+mIW89dTr7oC0WsJ54x5djhqsfK2h5n5uk32HpYXEc8C5yyYY4ASYzmw17Onk/9YsAzJTDk5/4CiIKUsV31pxkiltEinqGeED2PGnzj7G31MYqbhK0uMbGuKrI6jNLE9EhSjhXmtMm5LEgRIENm0qZnTeQqFU5eJQ3YQjmTcZfSFb6O/jw7TpNhMv6Kzei+JStdzQaFh4Igvgdm+fZsVf39DpHqK0/5a6seEDGhnG7+IumMbi/URr3uwal9emFsXuiUxqmrBk1QizSDa552cRrTHPAgMBAAECggEAEHDH/o2VFiG0wgL+2s/9HF0mUrWWxiuN7EtOBNrVCDWjs7/7Bsuo6Hoi5I7nbZ7R8sGlzaD/pe2dCtlxOez46C2pcSzSafRq/z8Dwy6RVM8raAOiXcM30X66HOnPn/TjxVv5wzuaHyrLvBOwOJYQN6a5MVbS+K6L0YeQSoVRK0k7If53CRfgx1YxntgspetNsXoD539f39zte3CHHj5XUF/tU7bNLMlt0CX3+KyXfi9kbJ2ivhR1t3n47UAdc9y//g91BDNq5IkZhlc8NxxRBPGygxopuvHNy0ISPhi+MhoxhgdnE1lX2rGW/PuZphLME4TXwKrdZJfbcIAPbVbqAQKBgQD5rYHxpEsV6dAKe6O7ce08tmVrzV98b+wZPRISwrybjP3ghMcZvBnTAeGXamlI/LgDAHasvhjb1wVChLDKuW/kfpCrjOOGOTpkEkVlZVXwFSYOkEdX2zyhZMLjRKTHpK5YiZ9UHqxBNAr3KwCTm0Q0IC0bqHkAUCn1mssqo0hpkQKBgQDLrXoNDGKXLPxaHbhdinpM+wiaO97atWTERtu8ok73laWFvQvczRcDv14hoseQ4MEJxcCaHe+6Lp0qk5OaDdeIzPW8msyJDb+I70P94rnTLPOyH5cq/2K2UVILdO/nblV+Mm6wXEgJ3EmWitKslSMC2Rw/JHLHeAPSeS/fq0M1XwKBgFLVtMnltx+TDfmcYYr71jiRTv7ACVDwlQUelNNylj6JPWVyx9eK54pxElY48KtNZQNh8P2IqBivssgJ29m2QiAtuXOg74+FhxDSWwGz6BoZ+iFUzsagLvJgyqO6D21I/qrTJfAzqPSM/qJYOv29wpgEoNKPR23KKtGYRJVlzM1xAoGAF/h9scVwYPxhYrW2ugOPKzosJALB0pmgl10DhWrQwmCxT1EVcVIN0FoYWPsQY6Of9Gd6qGi3iwDrbFRb/bh9UlNU5HKPed3NWe9W4C1r00eqEp+XKe9Ojch6UHDdvy4ED8sdrdHehJKRco86BiezLCWjJmdCvukIAiBTGw7L5R8CgYEAvRYYCwK2+XW5wCxXSxDxYVFbRI/e+rv6UUAwWStccf9uOh7ch5GpNFokmTZKYK7QF7scaI6evmySfCSLpIHd0+gHXqrAopQSZogdil5rE0j/NzWJsWEI9cq+KZTHb1IztyCI1PL5+PHrbiox3I+e8F1wvE2pZbJ61MMxUWZT2W4=");
        System.out.println("result"+result);*/
        //时间戳
        long timestamp = System.currentTimeMillis() / 1000;
        //随机数
        String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");
        String rsaPrivateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDGpcdU12Sco6EGaEDXKqm9RlteM8xy5QHheVAOArtsfetMcfjEqGMfGvehsIS+mIW89dTr7oC0WsJ54x5djhqsfK2h5n5uk32HpYXEc8C5yyYY4ASYzmw17Onk/9YsAzJTDk5/4CiIKUsV31pxkiltEinqGeED2PGnzj7G31MYqbhK0uMbGuKrI6jNLE9EhSjhXmtMm5LEgRIENm0qZnTeQqFU5eJQ3YQjmTcZfSFb6O/jw7TpNhMv6Kzei+JStdzQaFh4Igvgdm+fZsVf39DpHqK0/5a6seEDGhnG7+IumMbi/URr3uwal9emFsXuiUxqmrBk1QizSDa552cRrTHPAgMBAAECggEAEHDH/o2VFiG0wgL+2s/9HF0mUrWWxiuN7EtOBNrVCDWjs7/7Bsuo6Hoi5I7nbZ7R8sGlzaD/pe2dCtlxOez46C2pcSzSafRq/z8Dwy6RVM8raAOiXcM30X66HOnPn/TjxVv5wzuaHyrLvBOwOJYQN6a5MVbS+K6L0YeQSoVRK0k7If53CRfgx1YxntgspetNsXoD539f39zte3CHHj5XUF/tU7bNLMlt0CX3+KyXfi9kbJ2ivhR1t3n47UAdc9y//g91BDNq5IkZhlc8NxxRBPGygxopuvHNy0ISPhi+MhoxhgdnE1lX2rGW/PuZphLME4TXwKrdZJfbcIAPbVbqAQKBgQD5rYHxpEsV6dAKe6O7ce08tmVrzV98b+wZPRISwrybjP3ghMcZvBnTAeGXamlI/LgDAHasvhjb1wVChLDKuW/kfpCrjOOGOTpkEkVlZVXwFSYOkEdX2zyhZMLjRKTHpK5YiZ9UHqxBNAr3KwCTm0Q0IC0bqHkAUCn1mssqo0hpkQKBgQDLrXoNDGKXLPxaHbhdinpM+wiaO97atWTERtu8ok73laWFvQvczRcDv14hoseQ4MEJxcCaHe+6Lp0qk5OaDdeIzPW8msyJDb+I70P94rnTLPOyH5cq/2K2UVILdO/nblV+Mm6wXEgJ3EmWitKslSMC2Rw/JHLHeAPSeS/fq0M1XwKBgFLVtMnltx+TDfmcYYr71jiRTv7ACVDwlQUelNNylj6JPWVyx9eK54pxElY48KtNZQNh8P2IqBivssgJ29m2QiAtuXOg74+FhxDSWwGz6BoZ+iFUzsagLvJgyqO6D21I/qrTJfAzqPSM/qJYOv29wpgEoNKPR23KKtGYRJVlzM1xAoGAF/h9scVwYPxhYrW2ugOPKzosJALB0pmgl10DhWrQwmCxT1EVcVIN0FoYWPsQY6Of9Gd6qGi3iwDrbFRb/bh9UlNU5HKPed3NWe9W4C1r00eqEp+XKe9Ojch6UHDdvy4ED8sdrdHehJKRco86BiezLCWjJmdCvukIAiBTGw7L5R8CgYEAvRYYCwK2+XW5wCxXSxDxYVFbRI/e+rv6UUAwWStccf9uOh7ch5GpNFokmTZKYK7QF7scaI6evmySfCSLpIHd0+gHXqrAopQSZogdil5rE0j/NzWJsWEI9cq+KZTHb1IztyCI1PL5+PHrbiox3I+e8F1wvE2pZbJ61MMxUWZT2W4=";
        String merchantId = "1423599102";
        String certificateSerialNumber = "3B52ED8D3BF732DE332E38DE55D6252381973DC4";
        String serino = "23ABB448A8F3830B8D3D48187A6821D8AF7E6552";
        String body = "{\"channel_id\": \"20001111\"}";
        StringBuffer sb = new StringBuffer();
        sb.append("POST").append("\n");
        sb.append("/v3/apply4subject/applyment").append("\n");
        sb.append(timestamp).append("\n");
        sb.append(nonce_str).append("\n");
        sb.append(body).append("\n");
        //计算签名
        String sign = new String(Base64.encodeBase64(signRSA(sb.toString(), rsaPrivateKey)));
        System.out.println("签名sign值:" + sign);

        //拼装http头的Authorization内容
        String authorization = "WECHATPAY2-SHA256-RSA2048 mchid=\"" + merchantId + "\",nonce_str=\"" + nonce_str + "\",signature=\"" + sign + "\",timestamp=\"" + timestamp + "\",serial_no=\"" + serino + "\"";
        System.out.println("authorization值:" + authorization);

        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/apply4subject/applyment");
        //设置头部
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
        httpPost.addHeader("Authorization", authorization);
        httpPost.addHeader("Wechatpay-Serial", certificateSerialNumber);


        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json;charset=UTF-8");
        if (StrUtil.isNotEmpty(certificateSerialNumber)) {
            headers.put("Wechatpay-Serial", certificateSerialNumber);
        }
        headers.put("Accept", cn.hutool.http.ContentType.JSON.toString());
        headers.put("Authorization", authorization);
        HttpResponse httpResponse = HttpRequest.get("https://api.mch.weixin.qq.com/v3/apply4subject/applyment")
                .addHeaders(headers)
                .body(body)
                .execute();


        //获取返回内容
        CloseableHttpResponse response = httpclient.execute(httpPost);
        HttpEntity httpEntity = response.getEntity();
        String rescontent = new String(InputStreamTOByte(httpEntity.getContent()));
        JSONObject jsonObject = JSON.parseObject(rescontent);
        System.out.println("返回内容:" + rescontent);
    }
}
